package com.api.common.alert;


import com.api.common.alert.model.AlertMessage;
import com.api.common.alert.model.AlertStatistics;
import com.api.common.alert.model.AlertTypeEnums;
import com.api.common.alert.notififer.EmailNotifier;
import com.api.common.alert.notififer.Notifier;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;

/**
 * 告警管理器
 * 负责告警的聚合、去重、静默期控制
 */
@Component
@Slf4j
@ConditionalOnProperty(prefix = "alert",name = "enabled",havingValue = "true")
public class AlertManager {

    @Resource
    private List<Notifier> notifiers;

    //静默时间
    @Value("${alert.silence-period-minutes:10}")
    private int silencePeriodMinutes;

    //达到阈值就进行告警
    @Value("${alert.consecutive-threshold:3}")
    private int consecutiveThreshold;

    // 告警统计
    private final Map<String, AlertStatistics> alertStats = new ConcurrentHashMap<>();

    @Resource(name = "alertExecutor")
    private Executor alertExecutor;

    /**
     * 处理告警事件
     */
    public void process(AlertMessage event){
        String key=event.getAlertType()+":"+event.getSource();

        //1.更新统计
        AlertStatistics stats = alertStats.computeIfAbsent(key, k -> new AlertStatistics());
        stats.increment();
        stats.setLastAlertTime(LocalDateTime.now());

        //2.检查是否需要告警
        if(!shouldAlert(event,stats)){
            log.debug("告警被抑制 | 类型={}, 源={}, 原因={}",
                    event.getAlertType(), event.getSource(),
                    stats.isInSilencePeriod(silencePeriodMinutes) ? "静默期" : "未达到阈值");
            return;
        }
        AlertTypeEnums notifierType = event.getNotifierType();
        if(notifierType!=null&&( StringUtils.isBlank(notifierType.getType())||
                AlertTypeEnums.getEnums(notifierType.getType())==null)){
            log.debug("指定告警类型不存在");
            return;
        }
        //3.发送通知
        sendNotifications(event);

        //4.重置统计
        stats.resetConsecutiveCount();
    }

    /**
     * 发送通知到所有启用的渠道（使用线程池异步发送）
     */
    private void sendNotifications(AlertMessage event) {
        for (Notifier notifier : notifiers) {
            if(notifier.isEnabled()){
                alertExecutor.execute(()->{
                    try {
                        if(notifier instanceof EmailNotifier){
                            EmailNotifier emailNotifier=(EmailNotifier) notifier;
                            emailNotifier.setTo(event.getToEmail());
                        }else{
                            notifier.send(event);
                        }

                    }catch (Exception e){
                        log.error("通知发送失败 | 渠道={}, 原因={}",
                                notifier.getChannel(), e.getMessage(), e);
                    }
                });
            }
        }
    }

    /**
     * 判断是否应该发送告警
     */
    private boolean shouldAlert(AlertMessage event, AlertStatistics stats) {
        //静默期检查
        if(stats.isInSilencePeriod(silencePeriodMinutes)){
            return false;
        }

        //连续失败次数检查（仅对故障类告警）
        if(event.getAlertType().contains("FAILURE")||event.getAlertType().contains("SATURATED")){
            return stats.getConsecutiveCount()>=consecutiveThreshold;
        }
        return true;
    }
}
